/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.client.plugin;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;

import com.edi.Constant;
import com.edi.Kola;
import com.edi.client.param.EdiClientParam;
import com.edi.client.param.EdiSPOClientParam;
import com.edi.client.param.EdiServerParam;
import com.edi.manager.ServiceManager;
import com.edi.pubsub.EdiService;
import com.edi.pubsub.LocalService;

/**
 * 脚本插件，保存设计时定义的服务器端的脚本服务
 * 
 * @author 红木
 * 
 */
public class ScriptPlugin implements Plugin {
	private static final Log log = LogFactory.getLog(ScriptPlugin.class);
	private Class pluginClazz;
	private Map<String, PluginMethod> methodList;
	private String pluginName;

	public ScriptPlugin(Class pluginClazz, boolean needInit) {
		log.debug(" pluginClazz.getName() =" + pluginClazz.getName());
		this.pluginClazz = pluginClazz;
		//this.pluginName = StringUtils.substringAfterLast(pluginClazz.getName(), ".");    修改：插件名称应该为类名称  pluginClazz.getName()  cya 2009-3-18
		this.pluginName = pluginClazz.getName();
		methodList = new HashMap<String, PluginMethod>();
		if (needInit)
			;
		init();
	}

	public String getName() {
		return this.pluginName;
	}

	public void init() {
		methodList.clear();
		Method[] methods = pluginClazz.getDeclaredMethods();
		log.debug(" plugin methods =" + methods.length);
		ServiceManager serviceManager = Kola.getServiceManager();
		for (Method m : methods) {
			if (m.getName().indexOf("service") == 0) {

				PluginMethod pluginMethod = new PluginMethod(m, pluginClazz);

				methodList.put(m.getName(), pluginMethod);

				StringBuffer serviceName = new StringBuffer(pluginName)
						.append(".");
				serviceName.append(m.getName());
				log.debug("add  serviceName  =" + serviceName);
				EdiService ediService = new LocalService(serviceName.toString());
				serviceManager.addService(ediService);
			}
		}
	}

	/**
	 * 客户端调用动态脚本方法
	 */
	public PluginResult invoke(EdiClientParam param) throws Exception {
		log.debug(" enter plugin invoke ");
		Element clientPara = param.getEdiPara();
		log.debug(" clientPara =" + clientPara.asXML());
		log.debug("param.getServiceName() =" + param.getServiceName());
		String methodName = "";
		if (!StringUtils.contains(param.getServiceName(), ":"))
			methodName = StringUtils.substringAfterLast(param.getServiceName(),
					".");
		else
			methodName = StringUtils.substringAfterLast(param.getServiceName(),
					":");
		log.debug(" methodName =" + methodName);
		List<String> args = ((EdiSPOClientParam) param).getArgs();

		PluginResult pr = new CommonPluginResult();
		pr.setDsName(param.getDsName());
		PluginMethod pm = methodList.get(methodName);
		log.debug(" pm =" + (pm == null));
		if (pm == null) {
			pr.setErrorInfo("未找到指定的服务方法");
			pr.setState(Constant.EXEC_STATE_ERROR);
			return pr;
		}
		try {
			Object invokeResult = pm.clientInvoke(args);
			pr.setState(Constant.EXEC_STATE_SUCESS);
			pr.setResult(invokeResult);
		} catch (Exception e) {
			e.printStackTrace();
			ByteArrayOutputStream bop = new ByteArrayOutputStream();
			e.printStackTrace(new PrintStream(bop));
			String errorInfo = new String(bop.toByteArray());
			bop.close();
			pr.setState(Constant.EXEC_STATE_ERROR);
			pr.setErrorInfo(errorInfo);
		}
		return pr;
	}

	/**
	 * 服务器端调用动态脚本方法
	 */
	public PluginResult invoke(EdiServerParam param) throws Exception {
		PluginResult pr = new CommonPluginResult();
		String methodName = "";
		if (!StringUtils.contains(param.getServiceName(), ":"))
			methodName = StringUtils.substringAfterLast(param.getServiceName(),
					".");
		else
			methodName = StringUtils.substringAfterLast(param.getServiceName(),
					":");
		log.debug(" methodName =" + methodName);
		log.debug("插件方法为：" + param.getServiceName());
		PluginMethod pm = methodList.get(methodName);
		if (pm == null) {
			log.error("未发现制定的服务方法：" + param.getServiceName());
			pr.setErrorInfo("未找到指定的服务方法");
			pr.setState(Constant.EXEC_STATE_ERROR);
			return pr;
		}
		try {
			log.debug("开始执行插件方法：" + methodName);
			Object invokeResult = pm.serverInvoke(param.getParams());
			log.debug("执行结果为：" + invokeResult);
			log.debug(" invokeResult =" + (invokeResult.getClass()));
			pr.setState(Constant.EXEC_STATE_SUCESS);
			pr.setResult(invokeResult);
		} catch (Exception e) {
			e.printStackTrace();
			ByteArrayOutputStream bop = new ByteArrayOutputStream();
			e.printStackTrace(new PrintStream(bop));
			String errorInfo = new String(bop.toByteArray());
			bop.close();
			pr.setState(Constant.EXEC_STATE_ERROR);
			pr.setErrorInfo(errorInfo);
		}
		return pr;
	}

	public void dispose() {
		Method[] methods = pluginClazz.getDeclaredMethods();
		ServiceManager serviceManager = Kola.getServiceManager();
		for (Method m : methods) {
			if (m.getName().indexOf("service") == 0) {
				StringBuffer serviceName = new StringBuffer(pluginName)
						.append(".");
				serviceName.append(m.getName());
				serviceManager.removeService(serviceName.toString());
			}
		}

	}

	public void addMethod(String name, PluginMethod pluginMethod) {
		this.methodList.put(name, pluginMethod);
	}
}
